package cn.com.captureNetPacket;
import cn.com.captureNetPacket.model.NetworkCardInfo;
import lombok.Data;
import org.jnetpcap.packet.PcapPacket;
import org.jnetpcap.packet.format.FormatUtils;
import org.jnetpcap.protocol.lan.Ethernet;
import org.jnetpcap.protocol.network.Arp;
import org.jnetpcap.protocol.network.Icmp;
import org.jnetpcap.protocol.network.Ip4;
import org.jnetpcap.protocol.network.Ip6;
import org.jnetpcap.protocol.tcpip.Tcp;
import org.jnetpcap.protocol.tcpip.Udp;
import org.jnetpcap.protocol.voip.Rtp;
import org.jnetpcap.protocol.voip.Sdp;
import org.jnetpcap.protocol.voip.Sip;

import cn.com.captureNetPacket.model.NetworkInfo;
import cn.com.captureNetPacket.voice.AnalysisRTP;
import cn.com.captureNetPacket.voice.AnalysisSIP;
import lombok.extern.slf4j.Slf4j;

import java.time.LocalDateTime;

@Slf4j
@Data
public class AnalysisPacket {

	private NetworkCardInfo networkCardInfo;

	public AnalysisPacket(NetworkCardInfo networkCardInfo){
         this.networkCardInfo=networkCardInfo;
	}

		private String name;
	 
	public  void  analysisPacket(PcapPacket pcapPacket ){
		this.networkCardInfo.setLastRecivePacketTime(LocalDateTime.now());
		int  sourcePort = 0,destinationPort = 0;
		String sourceIP ="",destinationIP = "",sourceMac="",destinationMac="",transportLayer="TCP";int flags_DF=-1,flags_MF=-1,checksum=-1;
		int rtp_forward_channel_port = -1;
		  Tcp tcp = new Tcp();
          Udp udp = new Udp();
          Sip sip=new Sip();
          
        
          Ip4 ip4 = new Ip4();boolean isFragment=false;
          Ip6 ip6=new Ip6();
          Ethernet ethernet= new Ethernet();
          ethernet=pcapPacket.getHeader(ethernet);
		  if(ethernet!=null) {
			  sourceMac = FormatUtils.asString(ethernet.source());
			  destinationMac = FormatUtils.asString(ethernet.destination());
		  }
		pcapPacket.getCaptureHeader().timestampInMillis();
//          pcapPacket.getCaptureHeader().timestampInMicros();//抓取时间 。微妙
//          pcapPacket.getCaptureHeader().timestampInMillis();//抓取时间 。毫秒
        //  ethernet.getIndex();ethernet.getNextHeaderId();
          
          if(pcapPacket.hasHeader(ip4))
		{
        	  sourceIP=FormatUtils.ip(ip4.source());
        	  destinationIP=FormatUtils.ip(ip4.destination());
        	 
        	/* 
                                        没有对IP层分片的分析，太麻烦，IP层进行分片会很麻烦，而且开销很大，一旦丢失一份IP包，整个IP包要重传，所以IP层一般交换机mtu值1500字节，
        	  标志(flag)　占3位，但目前只有2位有意义。 
        	  ●　标志字段中的最低位记为MF(More Fragment)。MF=1即表示后面“还有分片”的数据报。MF=0表示这已是若干数据报片中的最后一个 
        	  ●　标志字段中间的一位记为DF(Don’t Fragment)，意思是“不能分片”。只有当DF=0时才允许分片。 
        	  
        	  
        	  
        	  */
        	  flags_DF=ip4.flags_DF();
        	  flags_MF=ip4.flags_MF();
        	  checksum=ip4.checksum();
        	  isFragment=ip4.isFragmented();
        	  
        	  
        	  if(CaptureNetPacketService.ipLogOpen) {
				  log.info("CaptureHeader###===>sourceIP:{}  mac:{}->destinationIP:{} mac:{} caplen：" + pcapPacket.getCaptureHeader().caplen() + "  wirelen:" + pcapPacket.getCaptureHeader().wirelen() + " FrameNumber:" + pcapPacket.getFrameNumber()
								  + " getAllocatedMemorySize:" + pcapPacket.getAllocatedMemorySize() + " getHeaderCount:" + pcapPacket.getHeaderCount() + " getTotalSize:" + pcapPacket.getTotalSize()
								  + " getCaptureHeader:" + pcapPacket.getCaptureHeader().getStructName() + " getFlowKey:" + pcapPacket.getFlowKey().getFlags()
						  , sourceIP, sourceMac, destinationIP, destinationMac
				  );
				  if(ip4.isFragmented() )
				  {
					  log.debug(transportLayer+"协议  sourceIP:"+sourceIP+"->\t destinationIP:"+destinationIP+"  ..  sourceMac:"+sourceMac+"-> destinationMac:"+destinationMac+"这两个之间发送了大数据了");
				  }

			  }
        	  
        	  
        	  

       
        	  
        	  
         if(pcapPacket.hasHeader(tcp)  )
		 {
			sourcePort=tcp.source();
			destinationPort=tcp.destination();
			NetworkInfo netInfo=new NetworkInfo(sourceIP, destinationIP, sourceMac, destinationMac, transportLayer, sourcePort, destinationPort);
			if(CaptureNetPacketService.tcpLogOpen) {
				log.debug("TCP sourceIP:{} port{} mac:{}->destinationIP:{}  port{}  mac:{} ", sourceIP, sourcePort, sourceMac, destinationIP, destinationPort, destinationMac);
			}
			if(CaptureNetPacketService.analysisTcp) {
				netInfo.setFrameNumber(pcapPacket.getFrameNumber());
				//log.warn("  "+netInfo.getBaseNetworkInfoKey()+" =======-------》"+"  FrameNumber:"+netInfo.getFrameNumber());
				//sip协议
				// get the source ip of the caller from the invite message.
				// seems to be a tricky and dirty workaround, poor jnetpcap framework!
//		         if(pcapPacket.hasHeader(sip) && pcapPacket.hasHeader(sdp)) {
//		        	  transportLayer="SIP";
//		        	  log.debug(transportLayer+"---------------s------不是tcp也不是udp");
//		             if( (sip.getUTF8String(0, '@')).startsWith("INVITE ") ) {
//		                 String sdptext = sdp.text();
//		                 int pos = sdptext.indexOf("m=audio ") + 8;
//		                 int end = pos;
//		                 if(pos != -1)
//		                     while(sdptext.charAt(end) != ' ') end++;
//                        //rtp流的udp端口号
//		                 rtp_forward_channel_port = Integer.parseInt(sdptext.substring(pos, end));
//		                 }
//		         }
//		         else 	analysisTCP(netInfo,ip4,tcp);
			}
		}else if(pcapPacket.hasHeader(udp) ){
			try {
				sourcePort = udp.source();
				destinationPort = udp.destination();
				transportLayer = "UDP";
				NetworkInfo netInfo = new NetworkInfo(sourceIP, destinationIP, sourceMac, destinationMac, transportLayer, sourcePort, destinationPort);
				if (CaptureNetPacketService.udpLogOpen) {
					log.debug("UDP sourceIP:{} port{} mac:{}->destinationIP:{}  port{}  mac:{} ", sourceIP, sourcePort, sourceMac, destinationIP, destinationPort, destinationMac);
				}

				if(CaptureNetPacketService.analysisUdp){
				Rtp rtp = new Rtp();
//	           Rtcp rtcpApp=new RtcpApp();
//	         //  Rtcp rtcpSenderReport=new RtcpSenderReport();
//	        //   Rtcp rtcpReceiverReport=new RtcpReceiverReport();
//	           Rtcp rtcpBye=new RtcpBye();
//	           RtcpSDES rtcpSDES=new RtcpSDES();

				if (pcapPacket.hasHeader(rtp) && CaptureNetPacketService.analysisRtp) {
					netInfo.setTransportLayer("RTP");
					AnalysisRTP.addRtp(netInfo, rtp);

//                dos = getOutputStream(rtp.ssrc());
//                  dos.write(rtp.getPayload());
				} else if (pcapPacket.hasHeader(sip) && CaptureNetPacketService.analysisSip) {
					netInfo.setTransportLayer("SIP");
					Sdp sdp = new Sdp();
					try {
						if (pcapPacket.hasHeader(sdp)) {
							AnalysisSIP.addSip(netInfo, sip, sdp);
						} else AnalysisSIP.addSip(netInfo, sip, null);
					} catch (Exception e) {
						AnalysisSIP.addSip(netInfo, sip, null);
						log.error(" 解析SDP 包错误,只解SIP包。 SIP:{}", sip, e);
					}
				}
//			  else  if(pcapPacket.hasHeader(rtcpSDES)  && CaptureNetPacketService.analysisRtp) {
//		            	
//		            if(pcapPacket.hasHeader(rtcpBye)){
//            		 log.info( "byebye   sourceIP:{} port{} mac:{}->destinationIP:{}  port{}  mac:{} errmessage:",sourceIP,sourcePort,sourceMac,destinationIP,destinationPort,destinationMac);
//            	    }else rtcpBye=null;
//		         new AnalysisRTCP(netInfo,rtcpSDES,rtcpBye).startAnalysisRTP();

			}
			}catch (Exception e) {
				log.error("UDPerror sourceIP:{} port{} mac:{}->destinationIP:{}  port{}  mac:{} errmessage:",sourceIP,sourcePort,sourceMac,destinationIP,destinationPort,destinationMac,e);
			}
		}
		else {
			if(CaptureNetPacketService.analysisIP4Unknown){
				 Icmp icmp=new Icmp();
				 Arp arp=new Arp();
				 if(pcapPacket.hasHeader(icmp)){
					 log.debug( "icmp sourceIP:{}  mac:{}->destinationIP:{} mac:{}",sourceIP,sourceMac,destinationIP,destinationMac);
					 
				 }else if(pcapPacket.hasHeader(arp)){
					 log.debug( "ARP sourceIP:{}  mac:{}->destinationIP:{} mac:{}",sourceIP,sourceMac,destinationIP,destinationMac);
				 }
				 else  
					 {if(CaptureNetPacketService.IP4UnknownLogOpen)
					 log.debug( "未知包 sourceIP:{}  mac:{}->destinationIP:{} mac:{}",sourceIP,sourceMac,destinationIP,destinationMac);
					 }
			}
			
		}



		}
         else {
        	 if(CaptureNetPacketService.getAppConfig().isAnalysisIpv6()) {
				 try {
					if( pcapPacket.hasHeader(ip6)) {
						sourceIP=FormatUtils.ip(ip6.source());
						destinationIP=FormatUtils.ip(ip6.destination());
						log.debug("is IP v6 {} —> {}  mac {} -> {}", sourceIP, destinationIP,sourceMac,destinationMac);
					}else {
						log.debug(" ------->>>. 未知 包");
					}
				 }catch (Exception e){
					 log.warn("ip6解析错误",e);
				 }
        	  }
          }
		
		
		
	//	log.info(transportLayer+"协议  sourceIP:"+sourceIP+":"+sourcePort+"->\t destinationIP:"+destinationIP+":"+destinationPort+" <..> sourceMac:"+sourceMac+"-> destinationMac:"+destinationMac+" DF=MF=CD=IF:"+flags_DF+"="+flags_MF+"="+checksum+"="+isFragment);
		
		
		
		
	}
	
	public  void analysisTCP( NetworkInfo netInfo,Ip4 ip,Tcp tcp){
	String tcpid=netInfo.getNetworkInfoKey();
	try {
	AnalysisTCP aTCP= AnalysisTCP.getAnalysisTCPs().get(tcpid);
	if(aTCP==null) {
		aTCP=new AnalysisTCP();
	    
	}
	aTCP.setNetInfo(netInfo);
	 aTCP.addPacket(ip,tcp);
	} catch (Exception e) {
		  log.error("addPacket Exception",e);
	}
	
	}

	
	
	
	
}
